﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Collections.Concurrent;
using System.Linq.Expressions;

namespace Sparrow.Reflection
{
    public class FieldMetadata : MemberMetadata
    {
        public FieldMetadata(FieldInfo fieldInfo)
        {
            this.Name = fieldInfo.Name;

            this.Attributes = new List<AttributeMetadata>();
            foreach (var attr in fieldInfo.GetCustomAttributes(false))
            {
                this.Attributes.Add(new AttributeMetadata { Attribute = attr });
            }

            //copy some code from FastReflectionLib (http://fastreflectionlib.codeplex.com/)

            // target: (object)(((TInstance)instance).Field)

            // preparing parameter, object type
            var instance = Expression.Parameter(typeof(object), "instance");

            // non-instance for static method, or ((TInstance)instance)
            var instanceCast = fieldInfo.IsStatic ? null :
                Expression.Convert(instance, fieldInfo.ReflectedType);

            // ((TInstance)instance).Property
            var fieldAccess = Expression.Field(instanceCast, fieldInfo);

            // (object)(((TInstance)instance).Property)
            var castFieldValue = Expression.Convert(fieldAccess, typeof(object));

            // Lambda expression
            var lambda = Expression.Lambda<Func<object, object>>(castFieldValue, instance);

            this.Getter = lambda.Compile();

        }

        Func<object, object> Getter
        {
            get;
            set;
        }

        public object GetValue(object instance)
        {
            return this.Getter(instance);
        }
    }
}
